// 你是一个专业的小偷，计划偷窃沿街的房屋。每间房内都藏有一定的现金，影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统，如果两间相邻的房屋在同一晚上被小偷闯入，系统会自动报警。

// 给定一个代表每个房屋存放金额的非负整数数组，计算你 不触动警报装置的情况下 ，一夜之内能够偷窃到的最高金额。

//  

// 示例 1：

// 输入：[1,2,3,1]
// 输出：4
// 解释：偷窃 1 号房屋 (金额 = 1) ，然后偷窃 3 号房屋 (金额 = 3)。
//      偷窃到的最高金额 = 1 + 3 = 4 。
// 示例 2：

// 输入：[2,7,9,3,1]
// 输出：12
// 解释：偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9)，接着偷窃 5 号房屋 (金额 = 1)。
//      偷窃到的最高金额 = 2 + 9 + 1 = 12 。
//  

// 提示：

// 0 <= nums.length <= 100
// 0 <= nums[i] <= 400

#include <vector>
#include <algorithm>

using namespace std;

/* 动态规划
时间复杂度：O(n)
空间复杂度：O(n)
*/
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) return 0;
        if (n == 1) return nums[0];
        vector<int> dp(n + 1, 0); // dp[i] 表示偷到这个房子的最高金额(这个房子可偷可不偷)
        dp[1] = nums[0];
        for (int i{2}; i <= n; ++i) {
            dp[i] = max(dp[i-1], dp[i-2] + nums[i-1]);
        }
        return dp[n];
    }
};

/* 动态规划+滚动数组优化
时间复杂度：O(n)
空间复杂度：O(1)
*/
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) return 0;
        if (n == 1) return nums[0];
        int pre = nums[0]; // 存储前一个状态
        int cur = max(nums[0], nums[1]); // 存储当前状态
        for (int i{2}; i < n; ++i) {
            int temp = cur;
            cur = max(cur, pre + nums[i]);
            pre = temp;
        }
        return cur;
    }
};